package com.powernode.ssm.utils.pdf;

import cn.hutool.core.io.FileUtil;
import com.lowagie.text.*;
import com.lowagie.text.Font;
import com.lowagie.text.Image;
import com.lowagie.text.Rectangle;
import com.lowagie.text.pdf.*;
import com.powernode.ssm.pojo.po.TestPdfPo;
import com.powernode.ssm.utils.DateTimeUtils;
import org.apache.commons.compress.utils.IOUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Repository;

import java.awt.*;
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Repository
public class PdfGenerator {

    @Value("${export.template_path}")
    private String tempPath;

    /**
     * 重要参数和需要修改的方法
     * addHeaderInfo方法设置头信息字段
     * createDataTable方法设置表格列数
     */
    private static final boolean NEED_WATERMARK = true;//是否需要水印
    private static final boolean NEED_SEAL = true;//是否需要盖章
    private static final String WATERMARK_TEXT = "机密";//水印文字
    private static final String SEAL_IMAGE_PATH = "picture/seal.png"; //盖章图片路径
    private static final int ROWS_PER_PAGE = 20; //每页表格最多显示多少条数据
    private static final int COLUMNS_COUNT = 4; // 表格列数

    // 页面尺寸和边距设置
    private static final float MARGIN_TOP = 80f;
    private static final float MARGIN_BOTTOM = 100f;
    private static final float MARGIN_LEFT = 50f;
    private static final float MARGIN_RIGHT = 50f;

    // 表格设置
    private static final float TABLE_TOP_MARGIN = 20f;

    // 水印相关设置
    private static final float WATERMARK_FONT_SIZE = 48f;
    private static final int WATERMARK_ROTATION = -45;
    private static final Color WATERMARK_COLOR = new Color(200, 200, 200, 100); // 淡化效果


    // 每页预估最大记录数（用于初始化，实际会重新计算）
    private static final int ESTIMATED_RECORDS_PER_PAGE = 15;

    // 用于记录页码文字的绘制位置（由 addFooterWithActualCount() 设置）
    private float footerTextX = -1f;  // 初始化为无效值
    private float footerTextY = -1f;

    //初始化字体变量
    private Font titleFont;//pdf标题字体
    private Font headKeyFont;//pdf头信息固定字体
    private Font headValueFont;//pdf头信息填充字体
    private Font tableFont;//表格头信息字体
    private Font textFont;//填充数据字体
    private Font pageFont;//页码数据字体

    //加载中文字体
    {
        try {
            BaseFont chinese = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
            titleFont = new Font(chinese,16,Font.NORMAL);
            headKeyFont = new Font(chinese,14,Font.NORMAL);
            headValueFont = new Font(chinese,13,Font.NORMAL);
            tableFont = new Font(chinese,11,Font.NORMAL);
            textFont = new Font(chinese,9,Font.NORMAL);
            pageFont = new Font(chinese,8,Font.NORMAL);
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
    // 存储生成器状态
    private static class GeneratorState {
        int totalRecords;
        int currentPage = 0;           // 当前是第几页，从1开始
        int currentPageSize = 0;       // 当前页多少条数据
        int currentPageLoadSize = 0;   // 当前页已添加多少条数据
        int currentPageRemainSize = 0; // 当前页剩余多少条数据
        int totalPages = 0;            // 总页数，后面统计
        List<TestPdfPo> dataList;
    }

    public String savePdf2Path(List<TestPdfPo> dataList){
        String realExportPath = tempPath+"/"+"TestPdfPo"+".pdf";

        File file = FileUtil.file(tempPath);
        file.mkdirs();

        try {
            byte[] bytes = this.generatePdf(dataList);
            try (FileOutputStream fos = new FileOutputStream(realExportPath)) {
                fos.write(bytes);
            }

        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        return realExportPath;
    }

    public byte[] generatePdf(List<TestPdfPo> dataList) throws DocumentException, IOException {
        this.generatorState = new GeneratorState();
        this.generatorState.totalRecords = dataList.size();
        this.generatorState.dataList = dataList;

        Document document = new Document(PageSize.A4, MARGIN_LEFT, MARGIN_RIGHT, MARGIN_TOP, MARGIN_BOTTOM);
        ByteArrayOutputStream baos = new ByteArrayOutputStream();

        PdfWriter writer = PdfWriter.getInstance(document, baos);

        // 设置页眉页脚
        HeaderFooterEvent event = new HeaderFooterEvent(writer);
        writer.setPageEvent(event);

        document.open();

        // 添加标题
        addTitle(document);

        // 添加顶部信息（在第一页顶部）
        addHeaderInfo(document, dataList.size());

        // 创建并填充表格（分页处理）
        addDataTableWithPagination(document, writer);

        document.close();
        return baos.toByteArray();
    }

    // 存储生成器状态
    private GeneratorState generatorState;

    // 添加顶部信息
    private void addHeaderInfo(Document document, int totalRecords) throws DocumentException {

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日");
        String currentTime = sdf.format(new Date());

        /*头信息第一行*/
        PdfPTable head0 = createTable(new float[]{3, 1, 3});
        PdfPCell cell11 = createCell("测试地区：", "广州", "1");
        PdfPCell cell12 = createCell("", "", "1");
        PdfPCell cell13 = createCell("生成时间：", currentTime, "1");

        cell12.setPadding(5);
        cell12.setVerticalAlignment(Element.ALIGN_TOP);
        cell11.setBorderColorBottom(Color.white);
        cell12.setBorderColorBottom(Color.white);
        cell13.setBorderColorBottom(Color.white);
        cell11.setBorderWidthBottom(2);
        cell12.setBorderWidthBottom(2);
        cell13.setBorderWidthBottom(2);
        head0.addCell(cell11);
        head0.addCell(cell12);
        head0.addCell(cell13);

        head0.setHorizontalAlignment(0);
        document.add(head0);
        /*头信息第一行*/

        /*头信息第二行*/
        PdfPTable head1 = createTable(new float[]{3, 1, 3});
        PdfPCell cell21 = createCell("测试号码：", "12345678909", "1");
        PdfPCell cell22 = createCell("", "", "1");
        PdfPCell cell23 = createCell("审批人：", "测试人员", "1");

        cell22.setPadding(5);
        cell22.setVerticalAlignment(Element.ALIGN_TOP);
        cell21.setBorderColorBottom(Color.white);
        cell22.setBorderColorBottom(Color.white);
        cell23.setBorderColorBottom(Color.white);
        cell21.setBorderWidthBottom(2);
        cell22.setBorderWidthBottom(2);
        cell23.setBorderWidthBottom(2);
        head1.addCell(cell21);
        head1.addCell(cell22);
        head1.addCell(cell23);

        head1.setHorizontalAlignment(0);
        document.add(head1);
        /*头信息第二行*/

        /*头信息第三行*/
        PdfPTable head2 = createTable(new float[]{3, 1, 3});
        PdfPCell cell31 = createCell("测试年龄：", "20岁", "1");
        PdfPCell cell32 = createCell("", "", "1");
        PdfPCell cell33 = createCell("测试性别：", "男", "1");

        cell32.setPadding(5);
        cell32.setVerticalAlignment(Element.ALIGN_TOP);
        cell31.setBorderColorBottom(Color.white);
        cell32.setBorderColorBottom(Color.white);
        cell33.setBorderColorBottom(Color.white);
        cell31.setBorderWidthBottom(2);
        cell32.setBorderWidthBottom(2);
        cell33.setBorderWidthBottom(2);
        head2.addCell(cell31);
        head2.addCell(cell32);
        head2.addCell(cell33);

        head2.setHorizontalAlignment(0);
        document.add(head2);
        /*头信息第三行*/

    }

    private void addTitle(Document document) {
        Paragraph paragraph = new Paragraph("测试pdf标题", titleFont);
        titleFont.setColor(Color.RED);

        paragraph.setAlignment(1);//居中
        document.add(paragraph);

        Paragraph paragraphSpace = createParagraphSpace(2);
        document.add(paragraphSpace);

    }

    /**
     * 创建空白段落
     * @param num
     * @return
     */
    public Paragraph createParagraphSpace(int num){
        Paragraph paragraph = new Paragraph();
        for (int i = 0; i < num; i++) {
            paragraph.add(new Chunk("\n"));
        }
        return paragraph;
    }

    /**
     * 创建指定列宽、列数每一行的数据
     * @param widths
     * @return
     */
    private PdfPTable createTable(float[] widths){
        PdfPTable table = new PdfPTable(widths);
        table.setTotalWidth(800);
        table.setHorizontalAlignment(Element.ALIGN_CENTER);
        table.getDefaultCell().setBorder(Rectangle.NO_BORDER);
        return table;
    }

    /**
     * 创建pdf头信息单元格
     * @param key   固定文本
     * @param value 待填充文本
     * @param borderDisappear   间距
     * @return
     */
    private PdfPCell createCell(String key, String value, String borderDisappear){
        Phrase phrase = new Phrase();
        phrase.add(new Chunk(key, headKeyFont));
        phrase.add("：");
        phrase.add(new Chunk(value, headValueFont));

        PdfPCell cell = new PdfPCell();
        cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
        cell.setHorizontalAlignment(Element.ALIGN_LEFT);
        cell.setPhrase(phrase);
        cell.disableBorderSide(Integer.parseInt(borderDisappear));
        cell.setBorder(Rectangle.NO_BORDER);//去除边框
        return cell;
    }

    /**
     * 从外部的 TTF/TTC 文件加载中文字体，用于正确显示中文内容。
     * 注意：BaseFont.IDENTITY_H 是支持中文的关键，BaseFont.EMBEDDED 表示嵌入 PDF。
     * @param fontSize 字体大小
     * @param style 字体样式，如 Font.NORMAL, Font.BOLD, Font.ITALIC
     * @return 返回一个支持中文的 Font 对象
     */
    private Font getChineseFont(float fontSize, int style) {
        try {
            BaseFont baseFont = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
            // 创建 BaseFont，支持中文且嵌入 PDF

            // 构造 iText Font 对象
            return new Font(baseFont, fontSize, style);

        } catch (Exception e) {
            e.printStackTrace();
            // 加载失败时返回默认字体（可能不支持中文）
            return new Font(Font.HELVETICA, fontSize, style);
        }
    }

    // 创建数据表格并处理分页
    private void addDataTableWithPagination(Document document, PdfWriter writer) throws DocumentException {

        PdfPTable table = createDataTable();
        int currentPage = generatorState.currentPage = 0;
        int currentPageSize = 0;
        int size = generatorState.dataList.size();

        for (int i = 0; i < size; i++) {
            // 添加当前行数据到表格
            addPageData(table, i, i + 1); // 只添加当前行，您也可以优化为批量添加

            currentPageSize++;

            generatorState.currentPageSize = currentPageSize;//保存当前页表格数据数量
            generatorState.currentPageLoadSize = i + 1;//截止当前已加载数据数量
            generatorState.currentPageRemainSize = size - generatorState.currentPageLoadSize;

            // 如果当前页满了，或者已经是最后一条
            if (currentPageSize >= ROWS_PER_PAGE || i == size - 1) {

                // 统计总页数
                currentPage++;
                generatorState.currentPage = currentPage;

                // 添加表格到当前页
                document.add(table);

                // 如果不是第一页，先分页
                if (currentPage > 0) {
                    document.newPage();
                }

                // 重置表格和当前页行数
                table = createDataTable();
                currentPageSize = 0;
            }
        }

        // 最终统计总页数
        generatorState.totalPages = currentPage;
    }

    // 创建数据表格
    // ==================== 修改：createDataTable() 中的表头字体使用 getChineseFont() ====================
    private PdfPTable createDataTable() {
        PdfPTable table = new PdfPTable(COLUMNS_COUNT); // 4列
        table.setWidthPercentage(100);
        table.setSpacingBefore(10f);
        table.setSpacingAfter(10f);
        
        // 设置列宽
        float[] columnWidths = {1f, 2f, 2f, 2f};
        table.setWidths(columnWidths);

        // 表格标题
        try {
            Font headerFont = tableFont;
            table.addCell(createCell("ID", headerFont, true));
            table.addCell(createCell("字符串", headerFont, true));
            table.addCell(createCell("日期", headerFont, true));
            table.addCell(createCell("名称", headerFont, true));
        } catch (DocumentException e) {
            e.printStackTrace();
        }

        return table;
    }

    // 添加单页的数据
    // ==================== 修改：addPageData() 中的字体使用 getChineseFont() ====================
    private void addPageData(PdfPTable table, int startIndex, int endIndex) {
        Font contentFont = textFont;

        for (int i = startIndex; i < endIndex; i++) {
            TestPdfPo data = generatorState.dataList.get(i);
            try {
                table.addCell(createCell(String.valueOf(data.getId4()), contentFont, false));
                table.addCell(createCell(data.getStr4(), contentFont, false));
                table.addCell(createCell(data.getDate4(), contentFont, false));
                table.addCell(createCell(data.getName4(), contentFont, false));
            } catch (DocumentException e) {
                e.printStackTrace();
            }
        }
    }

    // 创建单元格
    // ==================== 修改：createCell() 方法中默认使用中文字体 ====================
    // ✅ 所有文本（包括表头和内容）都使用中文字体，不再使用 FontFactory.getFont(...)
    private PdfPCell createCell(String text, Font font, boolean isHeader) {
        PdfPCell cell = new PdfPCell(new Phrase(text, font));
        cell.setPadding(5f);
        cell.setHorizontalAlignment(Element.ALIGN_CENTER);
        cell.setVerticalAlignment(Element.ALIGN_MIDDLE);

        if (isHeader) {
            cell.setBackgroundColor(new Color(220, 220, 220));
            cell.setBorderWidth(1f);
        } else {
            cell.setBorderWidth(0.5f);
        }

        return cell;
    }

    // 页眉页脚事件处理类
    private class HeaderFooterEvent extends PdfPageEventHelper {
        private PdfWriter writer;

        public HeaderFooterEvent(PdfWriter writer) {
            this.writer = writer;
        }

        @Override
        public void onOpenDocument(PdfWriter writer, Document document) {
        }

        @Override
        public void onStartPage(PdfWriter writer, Document document) {
        }

        @Override
        public void onEndPage(PdfWriter writer, Document document) {
            try {
                handleOnEndPage(writer, document);

            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onCloseDocument(PdfWriter writer, Document document) {
        }

    }

    // 使用示例
    public static void main(String[] args) {
        try {
            // 模拟数据 - 实际使用时替换为数据库数据
            List<TestPdfPo> dataList = generateMockData(11);

            PdfGenerator generator = new PdfGenerator();
            byte[] pdfBytes = generator.generatePdf(dataList);

            // 保存到文件（测试用）
            try (FileOutputStream fos = new FileOutputStream("output.pdf")) {
                fos.write(pdfBytes);
            }

            System.out.println("PDF生成成功！");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // 生成模拟数据
    private static List<TestPdfPo> generateMockData(int count) {
        return java.util.stream.IntStream.range(0, count)
            .mapToObj(i -> {
                TestPdfPo po = new TestPdfPo();
                po.setId4(i + 1);
                po.setStr4("字符串数据" + (i + 1));
                po.setDate4(DateTimeUtils.dateString());
                po.setName4("名称" + (i + 1));
                return po;
            })
            .collect(Collectors.toList());
    }

    private void handleOnEndPage(PdfWriter writer, Document document) {
        PdfContentByte canvas = writer.getDirectContent();

        // 1. 添加水印（可添加一个或多个）
        if (NEED_WATERMARK){
            addWatermark(canvas, document, true);
        }

        // 2. 添加页脚统计信息（自动计算当前页记录数）
        addFooterWithActualCount(canvas, document, writer);

        // 3. 添加盖章图片
        if (NEED_SEAL){
            addSealImage(canvas, document);
        }
    }

    // 添加水印
    private void addWatermark(PdfContentByte canvas, Document document,boolean onlyOne) {
        try {
            PdfContentByte watermarkCanvas = canvas.getPdfWriter().getDirectContentUnder();
            if (watermarkCanvas == null) {
                watermarkCanvas = canvas;
            }

            // 开始文本模式
            watermarkCanvas.beginText();

            // 设置水印字体和颜色（淡化）
            BaseFont baseFont = titleFont.getBaseFont();
            watermarkCanvas.setFontAndSize(baseFont, WATERMARK_FONT_SIZE);
            watermarkCanvas.setColorFill(WATERMARK_COLOR);

            // 计算水印位置和旋转
            Rectangle pageSize = document.getPageSize();
            float x = pageSize.getWidth() / 2;
            float y = pageSize.getHeight() / 2;

            // 设置透明度
            PdfGState gs = new PdfGState();
            gs.setFillOpacity(0.5f); // 设置透明度为50%
            watermarkCanvas.setGState(gs);

            if (onlyOne){
                //只在页面中间添加一个水印
                watermarkCanvas.showTextAligned(
                        Element.ALIGN_CENTER,
                        WATERMARK_TEXT,
                        x,
                        y,
                        WATERMARK_ROTATION
                );
            }else {
                // 添加多个水印（覆盖整个页面）
                for (int i = 0; i < 5; i++) {
                    for (int j = 0; j < 3; j++) {
                        watermarkCanvas.showTextAligned(
                                Element.ALIGN_CENTER,
                                WATERMARK_TEXT,
                                x + (i - 2) * 150,
                                y + (j - 1) * 100,
                                WATERMARK_ROTATION
                        );
                    }
                }
            }

            watermarkCanvas.endText();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // 添加页脚统计信息（自动计算当前页实际记录数）
    // ==================== 修改：addFooterWithActualCount() 中的页脚字体使用 getChineseFont() ====================
    private void addFooterWithActualCount(PdfContentByte canvas, Document document,PdfWriter writer) {
        try {
            Rectangle pageSize = document.getPageSize();
            float pageWidth = pageSize.getWidth();

            // 计算当前页实际记录数
            int currentPage = generatorState.currentPage;
            int totalRecords = generatorState.totalRecords;

            // 计算当前页的记录范围
            int recordsPerPage = generatorState.currentPageSize;
            int totalPages = generatorState.totalPages;
            int loadSize = generatorState.currentPageLoadSize;
            int remainSize = generatorState.currentPageRemainSize;

            Font footerFont = pageFont;
            String footerText = String.format("(第 %d页，该页%d条数据，已加载%d条数据，" +
                            "剩余%d条数据，总数据%d条)",
                    currentPage, recordsPerPage, loadSize, remainSize, totalRecords);

            // 当前页码文字绘制位置（居中，距离底部 30 points）
            float textX = pageWidth / 2;  // 水平居中
            float textY = 30f;            // 距离页面底部 30 points

            // ✅ 关键：把当前页码文字的 X 和 Y 坐标保存到成员变量中
            footerTextX = textX;
            footerTextY = textY;

            ColumnText.showTextAligned(
                    canvas,
                    Element.ALIGN_CENTER,
                    new Phrase(footerText, footerFont), // ✅ 使用中文字体
                    textX,
                    textY,
                    0
            );
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // 添加盖章图片
    private void addSealImage(PdfContentByte canvas, Document document) {
        try {
            // ✅ 指定图片路径：放在 resources/picture/seal.png
            String imageFileName = SEAL_IMAGE_PATH;

            // ✅ 通过类加载器从 classpath（resources目录）获取图片输入流
            InputStream imageStream = getClass().getClassLoader().getResourceAsStream(imageFileName);

            if (imageStream == null) {
                System.err.println("❌ 无法加载盖章图片: " + imageFileName + "，请确认该文件已放入 resources/picture/ 目录");
            }

            // ✅ 将 InputStream 转为 byte[]
            byte[] imageBytes = IOUtils.toByteArray(imageStream);

            // ✅ 通过字节数组创建 iText 的 Image 对象
            Image sealImage = Image.getInstance(imageBytes);

            Rectangle pageSize = document.getPageSize();

            // 2. 设置图片大小
            float imageWidth = 70f;
            float imageHeight = 70f;
            sealImage.scaleAbsolute(imageWidth, imageHeight);

            // 3. 使用成员变量中的页码文字坐标，作为盖章图片位置
            float textX = footerTextX;  // 页码文字的 X（比如页面中心）
            float textY = footerTextY;  // 页码文字的 Y（比如距离底部 30）

            // 4. 设置盖章图片位置（这里示例：图片放在页码文字的正上方，稍微偏移）
            float imageX = textX - imageWidth / 2;  // 图片水平居中（与文字一样）
            float imageY = textY - 20f;             // 图片在文字下方 15 points（可调整）

            // 或者：图片在文字正上方：float imageY = textY - imageHeight - 5f;

            // 5. 设置透明度（水印效果）
            PdfGState gs = new PdfGState();
            gs.setFillOpacity(0.6f); // 透明度 60%
            canvas.setGState(gs);

            // 6. 设置图片位置并添加到画布
            sealImage.setAbsolutePosition(imageX, imageY);
            canvas.addImage(sealImage);

        } catch (Exception e) {
            e.printStackTrace();
            // 降级处理：可绘制文字 "[盖章]" 等
            try {
                PdfGState gs = new PdfGState();
                gs.setFillOpacity(0.6f);
                canvas.setGState(gs);
                ColumnText.showTextAligned(
                        canvas,
                        Element.ALIGN_CENTER,
                        new Phrase("[盖章]", tableFont),
                        footerTextX,  // 使用页码文字 X
                        footerTextY - 20f, // 文字下方一点
                        0
                );
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
    }

}